package ee.reliability.tool.logic;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import ee.reliability.tool.parser.Period;
import ee.reliability.tool.parser.Period.PeriodType;

public class Statistic {

	private final List<Period> periodList;

	public Statistic(List<Period> periodList) {
		this.periodList = new LinkedList<>();
		this.periodList.addAll(periodList);
	}

	public LinkedList<Element> getWorkStatistic(PeriodType periodType) {
		LinkedList<Element> elementList = new LinkedList<>();
		LinkedList<Double> hourList = new LinkedList<>();

		for (Period period : periodList)
			if(period.getPeriodType() == periodType)
				hourList.add(period.getRealHours());

		if(hourList.isEmpty())
			return new LinkedList<>();
		Collections.sort(hourList);

		double min = hourList.getFirst();
		double max = hourList.getLast();

		double sqrt = Math.sqrt(hourList.size());
		int N = (int)sqrt;
		if( sqrt > N)
			N++;

		double step = (max - min) / N;
		for(int i = 0; i < N; i++)
			elementList.add(new Element(min + i*step, min + (i+1) * step));
		for(Double hour : hourList)
			for(Element element : elementList)
				if(elementList.getFirst().getMin() == element.getMin()){
					if(element.getMin() <= hour && hour <= element.getMax())
						element.setMi(element.getMi()+1);
				}else
					if(element.getMin() < hour && hour <= element.getMax())
						element.setMi(element.getMi()+1);
		int totalMi = 0;
		double prevF = 0;
		for (Element element : elementList){
			element.setFi((double)element.getMi()/hourList.size());
			totalMi += element.getMi();
			element.setF((double)totalMi/hourList.size());
			element.setMti((element.getF() - prevF)/hourList.size());
			prevF = element.getF();
		}

		return elementList;
	}

	public double getAverage(PeriodType periodType) {
		double total = 0;
		int count = 0;
		for (Period period : periodList)
			if(period.getPeriodType() == periodType){
				total += period.getRealHours();
				count++;
			}

		return count == 0 ? 0 : total/count;
	}

	public double getStdDeviation(PeriodType periodType) {
		double avg = getAverage(periodType);

		double total = 0;
		int count = 0;
		for (Period period : periodList)
			if(period.getPeriodType() == periodType){
				total += Math.pow(period.getRealHours() - avg, 2);
				count++;
			}

		return count == 0 ? 0 : Math.sqrt(total/count);
	}

	public double getVariationCoefficient(PeriodType periodType){
		double avg = getAverage(periodType);
		return avg == 0 ? 0 : getStdDeviation(periodType)/avg;
	}

	public static class Element{
		private final double min;
		private final double max;
		private int mi = 0;
		private double mti = 0;
		private double Fi = 0;
		private double F = 0;

		public Element(double min, double max) {
			this.min = min;
			this.max = max;
		}

		public double getMin() {
			return min;
		}

		public double getMax() {
			return max;
		}

		public int getMi() {
			return mi;
		}

		public void setMi(int mi) {
			this.mi = mi;
		}

		public double getMti() {
			return mti;
		}

		public void setMti(double mti) {
			this.mti = mti;
		}

		public double getFi() {
			return Fi;
		}

		public void setFi(double fi) {
			Fi = fi;
		}

		public double getF() {
			return F;
		}

		public void setF(double f) {
			F = f;
		}


	}
}
